home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / X11R4 / cmds / X / ddx / mi / mizerarc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-02-15  |  17.5 KB  |  770 lines

  1. /************************************************************
  2. Copyright 1989 by The Massachusetts Institute of Technology
  3.  
  4. Permission to use, copy, modify, and distribute this
  5. software and its documentation for any purpose and without
  6. fee is hereby granted, provided that the above copyright
  7. notice appear in all copies and that both that copyright
  8. notice and this permission notice appear in supporting
  9. documentation, and that the name of MIT not be used in
  10. advertising or publicity pertaining to distribution of the
  11. software without specific prior written permission.
  12. M.I.T. makes no representation about the suitability of
  13. this software for any purpose. It is provided "as is"
  14. without any express or implied warranty.
  15.  
  16. Author:  Bob Scheifler, MIT X Consortium
  17.  
  18. ********************************************************/
  19.  
  20. /* $XConsortium: mizerarc.c,v 5.24 89/11/25 12:33:17 rws Exp $ */
  21.  
  22. /* Derived from:
  23.  * "Algorithm for drawing ellipses or hyperbolae with a digital plotter"
  24.  * by M. L. V. Pitteway
  25.  * The Computer Journal, November 1967, Volume 10, Number 3, pp. 282-289
  26.  */
  27.  
  28. #include <math.h>
  29. #include "X.h"
  30. #include "Xprotostr.h"
  31. #include "miscstruct.h"
  32. #include "gcstruct.h"
  33. #include "pixmapstr.h"
  34. #include "mi.h"
  35. #include "mizerarc.h"
  36.  
  37. #define FULLCIRCLE (360 * 64)
  38. #define OCTANT (45 * 64)
  39. #define QUADRANT (90 * 64)
  40. #define HALFCIRCLE (180 * 64)
  41. #define QUADRANT3 (270 * 64)
  42.  
  43. #ifndef M_PI
  44. #define M_PI    3.14159265358979323846
  45. #endif
  46.  
  47. #define Dsin(d)    ((d) == 0 ? 0.0 : ((d) == QUADRANT ? 1.0 : \
  48.          ((d) == HALFCIRCLE ? 0.0 : \
  49.          ((d) == QUADRANT3 ? -1.0 : sin((double)d*(M_PI/11520.0))))))
  50.  
  51. #define Dcos(d)    ((d) == 0 ? 1.0 : ((d) == QUADRANT ? 0.0 : \
  52.          ((d) == HALFCIRCLE ? -1.0 : \
  53.          ((d) == QUADRANT3 ? 0.0 : cos((double)d*(M_PI/11520.0))))))
  54.  
  55. typedef struct {
  56.     DDXPointRec startPt;
  57.     DDXPointRec endPt;
  58.     int dashIndex;
  59.     int dashOffset;
  60.     int dashIndexInit;
  61.     int dashOffsetInit;
  62. } DashInfo;
  63.  
  64. static miZeroArcPtRec oob = {65536, 65536, 0};
  65.  
  66. /*
  67.  * (x - l)^2 / (W/2)^2  + (y + H/2)^2 / (H/2)^2 = 1
  68.  *
  69.  * where l is either 0 or .5
  70.  *
  71.  * alpha = 4(W^2)
  72.  * beta = 4(H^2)
  73.  * gamma = 0
  74.  * u = 2(W^2)H
  75.  * v = 4(H^2)l
  76.  * k = -4(H^2)(l^2)
  77.  *
  78.  */
  79.  
  80. Bool
  81. miZeroArcSetup(arc, info, ok360)
  82.     register xArc *arc;
  83.     register miZeroArcRec *info;
  84.     Bool ok360;
  85. {
  86.     int l;
  87.     int angle1, angle2;
  88.     int startseg, endseg;
  89.     int startAngle, endAngle;
  90.     int i, overlap;
  91.     miZeroArcPtRec start, end;
  92.  
  93.     l = arc->width & 1;
  94.     if (arc->width == arc->height)
  95.     {
  96.     info->alpha = 4;
  97.     info->beta = 4;
  98.     info->k1 = -8;
  99.     info->k3 = -16;
  100.     info->b = 12;
  101.     info->a = (arc->width << 2) - 12;
  102.     info->d = 17 - (arc->width << 1);
  103.     if (l)
  104.     {
  105.         info->b -= 4;
  106.         info->a += 4;
  107.         info->d -= 7;
  108.     }
  109.     }
  110.     else if (!arc->width || !arc->height)
  111.     {
  112.     info->alpha = 0;
  113.     info->beta = 0;
  114.     info->k1 = 0;
  115.     info->k3 = 0;
  116.     info->a = -arc->height;
  117.     info->b = 0;
  118.     info->d = -1;
  119.     }
  120.     else
  121.     {
  122.     /* initial conditions */
  123.     info->alpha = (arc->width * arc->width) << 2;
  124.     info->beta = (arc->height * arc->height) << 2;
  125.     info->k1 = info->beta << 1;
  126.     info->k3 = info->k1 + (info->alpha << 1);
  127.     info->b = l ? 0 : -info->beta;
  128.     info->a = info->alpha * arc->height;
  129.     info->d = info->b - (info->a >> 1) - (info->alpha >> 2);
  130.     if (l)
  131.         info->d -= info->beta >> 2;
  132.     info->a -= info->b;
  133.     /* take first step, d < 0 always */
  134.     info->b -= info->k1;
  135.     info->a += info->k1;
  136.     info->d += info->b;
  137.     /* octant change, b < 0 always */
  138.     info->k1 = -info->k1;
  139.     info->k3 = -info->k3;
  140.     info->b = -info->b;
  141.     info->d = info->b - info->a - info->d;
  142.     info->a = info->a - (info->b << 1);
  143.     }
  144.     info->dx = 1;
  145.     info->dy = 0;
  146.     info->w = (arc->width + 1) >> 1;
  147.     info->h = arc->height >> 1;
  148.     info->xorg = arc->x + (arc->width >> 1);
  149.     info->yorg = arc->y;
  150.     info->xorgo = info->xorg + l;
  151.     info->yorgo = info->yorg + arc->height;
  152.     if (!arc->width && !arc->height)
  153.     {
  154.     info->x = 0;
  155.     info->y = 0;
  156.     info->initialMask = 1;
  157.     info->start = oob;
  158.     info->end = oob;
  159.     return FALSE;
  160.     }
  161.     if (!arc->width && arc->height)
  162.     {
  163.     info->x = 0;
  164.     info->y = 1;
  165.     }
  166.     else
  167.     {
  168.     info->x = 1;
  169.     info->y = 0;
  170.     }
  171.     angle1 = arc->angle1;
  172.     angle2 = arc->angle2;
  173.     if (angle2 > FULLCIRCLE)
  174.     angle2 = FULLCIRCLE;
  175.     else if (angle2 < -FULLCIRCLE)
  176.     angle2 = -FULLCIRCLE;
  177.     if (angle2 < 0)
  178.     {
  179.     startAngle = angle1 + angle2;
  180.     endAngle = angle1;
  181.     }
  182.     else
  183.     {
  184.     startAngle = angle1;
  185.     endAngle = angle1 + angle2;
  186.     }
  187.     if (startAngle < 0)
  188.     startAngle = FULLCIRCLE - (-startAngle) % FULLCIRCLE;
  189.     if (startAngle >= FULLCIRCLE)
  190.     startAngle = startAngle % FULLCIRCLE;
  191.     if (endAngle < 0)
  192.     endAngle = FULLCIRCLE - (-endAngle) % FULLCIRCLE;
  193.     if (endAngle >= FULLCIRCLE)
  194.     endAngle = endAngle % FULLCIRCLE;
  195.     info->startAngle = startAngle;
  196.     info->endAngle = endAngle;
  197.     if (ok360 && (startAngle == endAngle) && arc->angle2 &&
  198.     arc->width && arc->height)
  199.     {
  200.     info->initialMask = 0xf;
  201.     info->start = oob;
  202.     info->end = oob;
  203.     return TRUE;
  204.     }
  205.     startseg = startAngle / OCTANT;
  206.     if (!arc->height || (((startseg + 1) & 2) && arc->width))
  207.     {
  208.     start.x = Dcos(startAngle) * ((arc->width + 1) / 2.0);
  209.     if (start.x < 0)
  210.         start.x = -start.x;
  211.     start.y = -1;
  212.     }
  213.     else
  214.     {
  215.     start.y = Dsin(startAngle) * (arc->height / 2.0);
  216.     if (start.y < 0)
  217.         start.y = -start.y;
  218.     start.y = info->h - start.y;
  219.     start.x = 65536;
  220.     }
  221.     endseg = endAngle / OCTANT;
  222.     if (!arc->height || (((endseg + 1) & 2) && arc->width))
  223.     {
  224.     end.x = Dcos(endAngle) * ((arc->width + 1) / 2.0);
  225.     if (end.x < 0)
  226.         end.x = -end.x;
  227.     end.y = -1;
  228.     }
  229.     else
  230.     {
  231.     end.y = Dsin(endAngle) * (arc->height / 2.0);
  232.     if (end.y < 0)
  233.         end.y = -end.y;
  234.     end.y = info->h - end.y;
  235.     end.x = 65536;
  236.     }
  237.     info->firstx = start.x;
  238.     info->firsty = start.y;
  239.     info->initialMask = 0;
  240.     overlap = arc->angle2 && (endAngle <= startAngle);
  241.     for (i = 0; i < 4; i++)
  242.     {
  243.     if (overlap ?
  244.         ((i * QUADRANT <= endAngle) || ((i + 1) * QUADRANT > startAngle)) :
  245.         ((i * QUADRANT <= endAngle) && ((i + 1) * QUADRANT > startAngle)))
  246.         info->initialMask |= (1 << i);
  247.     }
  248.     start.mask = info->initialMask;
  249.     end.mask = info->initialMask;
  250.     startseg >>= 1;
  251.     endseg >>= 1;
  252.     overlap = overlap && (endseg == startseg);
  253.     if (start.x != end.x || start.y != end.y || !overlap)
  254.     {
  255.     if (startseg & 1)
  256.     {
  257.         if (!overlap)
  258.         info->initialMask &= ~(1 << startseg);
  259.         if (start.x > end.x || start.y > end.y)
  260.         end.mask &= ~(1 << startseg);
  261.     }
  262.     else
  263.     {
  264.         start.mask &= ~(1 << startseg);
  265.         if (((start.x < end.x || start.y < end.y) ||
  266.          (start.x == end.x && start.y == end.y && (endseg & 1))) &&
  267.         !overlap)
  268.         end.mask &= ~(1 << startseg);
  269.     }
  270.     if (endseg & 1)
  271.     {
  272.         end.mask &= ~(1 << endseg);
  273.         if (((start.x > end.x || start.y > end.y) ||
  274.          (start.x == end.x && start.y == end.y && !(startseg & 1))) &&
  275.         !overlap)
  276.         start.mask &= ~(1 << endseg);
  277.     }
  278.     else
  279.     {
  280.         if (!overlap)
  281.         info->initialMask &= ~(1 << endseg);
  282.         if (start.x < end.x || start.y < end.y)
  283.         start.mask &= ~(1 << endseg);
  284.     }
  285.     }
  286.     if (startseg & 1)
  287.     {
  288.     info->start = start;
  289.     info->end = oob;
  290.     }
  291.     else
  292.     {
  293.     info->end = start;
  294.     info->start = oob;
  295.     }
  296.     if (endseg & 1)
  297.     {
  298.     info->altend = end;
  299.     info->altstart = oob;
  300.     }
  301.     else
  302.     {
  303.     info->altstart = end;
  304.     info->altend = oob;
  305.     }
  306.     if (info->altstart.x < info->start.x || info->altstart.y < info->start.y)
  307.     {
  308.     miZeroArcPtRec tmp;
  309.      tmp = info->altstart;
  310.     info->altstart = info->start;
  311.     info->start = tmp;
  312.     }
  313.     if (info->altend.x < info->end.x || info->altend.y < info->end.y)
  314.     {
  315.     miZeroArcPtRec tmp;
  316.      tmp = info->altend;
  317.     info->altend = info->end;
  318.     info->end = tmp;
  319.     }
  320.     if (!info->start.x || !info->start.y)
  321.     {
  322.     info->initialMask = info->start.mask;
  323.     info->start = info->altstart;
  324.     }
  325.     return FALSE;
  326. }
  327.  
  328. #define Pixelate(xval,yval) \
  329.     { \
  330.     pts->x = xval; \
  331.     pts->y = yval; \
  332.     pts++; \
  333.     }
  334.  
  335. #define DoPix(idx,xval,yval) if (mask & (1 << idx)) Pixelate(xval, yval);
  336.  
  337. DDXPointPtr
  338. miZeroArcPts(arc, pts)
  339.     xArc *arc;
  340.     register DDXPointPtr pts;
  341. {
  342.     miZeroArcRec info;
  343.     register int x, y, a, b, d, mask;
  344.     register int k1, k3, dx, dy;
  345.     Bool do360;
  346.  
  347.     do360 = miZeroArcSetup(arc, &info, TRUE);
  348.     MIARCSETUP();
  349.     mask = info.initialMask;
  350.     if (!(arc->width & 1))
  351.     {
  352.     DoPix(1, info.xorgo, info.yorg);
  353.     DoPix(3, info.xorgo, info.yorgo);
  354.     }
  355.     if (!info.end.x || !info.end.y)
  356.     {
  357.     mask = info.end.mask;
  358.     info.end = info.altend;
  359.     }
  360.     if (do360 && (arc->width == arc->height) && !(arc->width & 1))
  361.     {
  362.     int yorgh = info.yorg + info.h;
  363.     int xorghp = info.xorg + info.h;
  364.     int xorghn = info.xorg - info.h;
  365.  
  366.     while (1)
  367.     {
  368.         Pixelate(info.xorg + x, info.yorg + y);
  369.         Pixelate(info.xorg - x, info.yorg + y);
  370.         Pixelate(info.xorg - x, info.yorgo - y);
  371.         Pixelate(info.xorg + x, info.yorgo - y);
  372.         if (a < 0)
  373.         break;
  374.         Pixelate(xorghp - y, yorgh - x);
  375.         Pixelate(xorghn + y, yorgh - x);
  376.         Pixelate(xorghn + y, yorgh + x);
  377.         Pixelate(xorghp - y, yorgh + x);
  378.         MIARCCIRCLESTEP(;);
  379.     }
  380.     if (x > 1 && pts[-1].x == pts[-5].x && pts[-1].y == pts[-5].y)
  381.         pts -= 4;
  382.     x = info.w;
  383.     y = info.h;
  384.     }
  385.     else if (do360)
  386.     {
  387.     while (y < info.h || x < info.w)
  388.     {
  389.         MIARCOCTANTSHIFT(;);
  390.         Pixelate(info.xorg + x, info.yorg + y);
  391.         Pixelate(info.xorgo - x, info.yorg + y);
  392.         Pixelate(info.xorgo - x, info.yorgo - y);
  393.         Pixelate(info.xorg + x, info.yorgo - y);
  394.         MIARCSTEP(;,;);
  395.     }
  396.     }
  397.     else
  398.     {
  399.     while (y < info.h || x < info.w)
  400.     {
  401.         MIARCOCTANTSHIFT(;);
  402.         if ((x == info.start.x) || (y == info.start.y))
  403.         {
  404.         mask = info.start.mask;
  405.         info.start = info.altstart;
  406.         }
  407.         DoPix(0, info.xorg + x, info.yorg + y);
  408.         DoPix(1, info.xorgo - x, info.yorg + y);
  409.         DoPix(2, info.xorgo - x, info.yorgo - y);
  410.         DoPix(3, info.xorg + x, info.yorgo - y);
  411.         if ((x == info.end.x) || (y == info.end.y))
  412.         {
  413.         mask = info.end.mask;
  414.         info.end = info.altend;
  415.         }
  416.         MIARCSTEP(;,;);
  417.     }
  418.     }
  419.     if ((x == info.start.x) || (y == info.start.y))
  420.     mask = info.start.mask;
  421.     DoPix(0, info.xorg + x, info.yorg + y);
  422.     DoPix(2, info.xorgo - x, info.yorgo - y);
  423.     if (arc->height & 1)
  424.     {
  425.     DoPix(1, info.xorgo - x, info.yorg + y);
  426.     DoPix(3, info.xorg + x, info.yorgo - y);
  427.     }
  428.     return pts;
  429. }
  430.  
  431. #undef DoPix
  432. #define DoPix(idx,xval,yval) \
  433.     if (mask & (1 << idx)) \
  434.     { \
  435.     arcPts[idx]->x = xval; \
  436.     arcPts[idx]->y = yval; \
  437.     arcPts[idx]++; \
  438.     }
  439.  
  440. static void
  441. miZeroArcDashPts(pGC, arc, dinfo, points, maxPts, evenPts, oddPts)
  442.     GCPtr pGC;
  443.     xArc *arc;
  444.     DashInfo *dinfo;
  445.     int maxPts;
  446.     register DDXPointPtr points, *evenPts, *oddPts;
  447. {
  448.     miZeroArcRec info;
  449.     register int x, y, a, b, d, mask;
  450.     register int k1, k3, dx, dy;
  451.     int dashRemaining;
  452.     DDXPointPtr arcPts[4];
  453.     DDXPointPtr startPts[5], endPts[5];
  454.     int deltas[5];
  455.     DDXPointPtr startPt, pt, lastPt, pts;
  456.     int i, j, delta, ptsdelta, seg, startseg;
  457.  
  458.     for (i = 0; i < 4; i++)
  459.     arcPts[i] = points + (i * maxPts);
  460.     (void)miZeroArcSetup(arc, &info, FALSE);
  461.     MIARCSETUP();
  462.     mask = info.initialMask;
  463.     startseg = info.startAngle / QUADRANT;
  464.     startPt = arcPts[startseg];
  465.     if (!(arc->width & 1))
  466.     {
  467.     DoPix(1, info.xorgo, info.yorg);
  468.     DoPix(3, info.xorgo, info.yorgo);
  469.     }
  470.     if (!info.end.x || !info.end.y)
  471.     {
  472.     mask = info.end.mask;
  473.     info.end = info.altend;
  474.     }
  475.     while (y < info.h || x < info.w)
  476.     {
  477.     MIARCOCTANTSHIFT(;);
  478.     if ((x == info.firstx) || (y == info.firsty))
  479.         startPt = arcPts[startseg];
  480.     if ((x == info.start.x) || (y == info.start.y))
  481.     {
  482.         mask = info.start.mask;
  483.         info.start = info.altstart;
  484.     }
  485.     DoPix(0, info.xorg + x, info.yorg + y);
  486.     DoPix(1, info.xorgo - x, info.yorg + y);
  487.     DoPix(2, info.xorgo - x, info.yorgo - y);
  488.     DoPix(3, info.xorg + x, info.yorgo - y);
  489.     if ((x == info.end.x) || (y == info.end.y))
  490.     {
  491.         mask = info.end.mask;
  492.         info.end = info.altend;
  493.     }
  494.     MIARCSTEP(;,;);
  495.     }
  496.     if ((x == info.firstx) || (y == info.firsty))
  497.     startPt = arcPts[startseg];
  498.     if ((x == info.start.x) || (y == info.start.y))
  499.     mask = info.start.mask;
  500.     DoPix(0, info.xorg + x, info.yorg + y);
  501.     DoPix(2, info.xorgo - x, info.yorgo - y);
  502.     if (arc->height & 1)
  503.     {
  504.     DoPix(1, info.xorgo - x, info.yorg + y);
  505.     DoPix(3, info.xorg + x, info.yorgo - y);
  506.     }
  507.     for (i = 0; i < 4; i++)
  508.     {
  509.     seg = (startseg + i) & 3;
  510.     pt = points + (seg * maxPts);
  511.     if (seg & 1)
  512.     {
  513.         startPts[i] = pt;
  514.         endPts[i] = arcPts[seg];
  515.         deltas[i] = 1;
  516.     }
  517.     else
  518.     {
  519.         startPts[i] = arcPts[seg] - 1;
  520.         endPts[i] = pt - 1;
  521.         deltas[i] = -1;
  522.     }
  523.     }
  524.     startPts[4] = startPts[0];
  525.     endPts[4] = startPt;
  526.     startPts[0] = startPt;
  527.     if (startseg & 1)
  528.     {
  529.     if (startPts[4] != endPts[4])
  530.         endPts[4]--;
  531.     deltas[4] = 1;
  532.     }
  533.     else
  534.     {
  535.     if (startPts[0] > startPts[4])
  536.         startPts[0]--;
  537.     if (startPts[4] < endPts[4])
  538.         endPts[4]--;
  539.     deltas[4] = -1;
  540.     }
  541.     if (arc->angle2 < 0)
  542.     {
  543.     DDXPointPtr tmps, tmpe;
  544.     int tmpd;
  545.  
  546.     tmpd = deltas[0];
  547.     tmps = startPts[0] - tmpd;
  548.     tmpe = endPts[0] - tmpd;
  549.     startPts[0] = endPts[4] - deltas[4];
  550.     endPts[0] = startPts[4] - deltas[4];
  551.     deltas[0] = -deltas[4];
  552.     startPts[4] = tmpe;
  553.     endPts[4] = tmps;
  554.     deltas[4] = -tmpd;
  555.     tmpd = deltas[1];
  556.     tmps = startPts[1] - tmpd;
  557.     tmpe = endPts[1] - tmpd;
  558.     startPts[1] = endPts[3] - deltas[3];
  559.     endPts[1] = startPts[3] - deltas[3];
  560.     deltas[1] = -deltas[3];
  561.     startPts[3] = tmpe;
  562.     endPts[3] = tmps;
  563.     deltas[3] = -tmpd;
  564.     tmps = startPts[2] - deltas[2];
  565.     startPts[2] = endPts[2] - deltas[2];
  566.     endPts[2] = tmps;
  567.     deltas[2] = -deltas[2];
  568.     }
  569.     for (i = 0; startPts[i] == endPts[i]; i++)
  570.     ;
  571.     pt = startPts[i];
  572.     for (j = 4; startPts[j] == endPts[i]; j--)
  573.     ;
  574.     lastPt = endPts[j] - deltas[j];
  575.     if ((pt->x == dinfo->endPt.x) && (pt->y == dinfo->endPt.y))
  576.     {
  577.     startPts[i] += deltas[i];
  578.     }
  579.     else
  580.     {
  581.     dinfo->dashIndex = dinfo->dashIndexInit;
  582.     dinfo->dashOffset = dinfo->dashOffsetInit;
  583.     }
  584.     if ((lastPt->x == dinfo->startPt.x) && (lastPt->y == dinfo->startPt.y) &&
  585.     (lastPt != pt))
  586.     endPts[j] = pt;
  587.     dinfo->startPt = *pt;
  588.     dinfo->endPt = *lastPt;
  589.     dashRemaining = pGC->dash[dinfo->dashIndex] - dinfo->dashOffset;
  590.     for (i = 0; i < 5; i++)
  591.     {
  592.     pt = startPts[i];
  593.     lastPt = endPts[i];
  594.     delta = deltas[i];
  595.     while (pt != lastPt)
  596.     {
  597.         if (dinfo->dashIndex & 1)
  598.         {
  599.         pts = *oddPts;
  600.         ptsdelta = -1;
  601.         }
  602.         else
  603.         {
  604.         pts = *evenPts;
  605.         ptsdelta = 1;
  606.         }
  607.         while ((pt != lastPt) && --dashRemaining >= 0)
  608.         {
  609.         *pts = *pt;
  610.         pts += ptsdelta;
  611.         pt += delta;
  612.         }
  613.         if (dinfo->dashIndex & 1)
  614.         *oddPts = pts;
  615.         else
  616.         *evenPts = pts;
  617.         if (dashRemaining <= 0)
  618.         {
  619.         if (++(dinfo->dashIndex) == pGC->numInDashList)
  620.             dinfo->dashIndex = 0;
  621.         dashRemaining = pGC->dash[dinfo->dashIndex];
  622.         }
  623.     }
  624.     }
  625.     dinfo->dashOffset = pGC->dash[dinfo->dashIndex] - dashRemaining;
  626. }
  627.  
  628. void
  629. miZeroPolyArc(pDraw, pGC, narcs, parcs)
  630.     DrawablePtr    pDraw;
  631.     GCPtr    pGC;
  632.     int        narcs;
  633.     xArc    *parcs;
  634. {
  635.     int maxPts = 0;
  636.     register int n, maxw;
  637.     register xArc *arc;
  638.     register int i;
  639.     DDXPointPtr points, pts, oddPts;
  640.     register DDXPointPtr pt;
  641.     int numPts;
  642.     Bool dospans;
  643.     int *widths;
  644.     unsigned long fgPixel = pGC->fgPixel;
  645.     DashInfo dinfo;
  646.  
  647.     for (arc = parcs, i = narcs; --i >= 0; arc++)
  648.     {
  649.     if (!miCanZeroArc(arc))
  650.         miPolyArc(pDraw, pGC, 1, arc);
  651.     else
  652.     {
  653.         if (arc->width > arc->height)
  654.         n = arc->width + (arc->height >> 1);
  655.         else
  656.         n = arc->height + (arc->width >> 1);
  657.         if (n > maxPts)
  658.         maxPts = n;
  659.     }
  660.     }
  661.     if (!maxPts)
  662.     return;
  663.     numPts = maxPts << 2;
  664.     dospans = (pGC->lineStyle != LineSolid) || (pGC->fillStyle != FillSolid);
  665.     if (dospans)
  666.     {
  667.     widths = (int *)ALLOCATE_LOCAL(sizeof(int) * numPts);
  668.     if (!widths)
  669.         return;
  670.     maxw = 0;
  671.     }
  672.     if (pGC->lineStyle != LineSolid)
  673.     {
  674.     numPts <<= 1;
  675.     dinfo.startPt.x = parcs->x - 1;
  676.     dinfo.startPt.y = parcs->y - 1;
  677.     dinfo.endPt = dinfo.startPt;
  678.     dinfo.dashIndexInit = 0;
  679.     dinfo.dashOffsetInit = 0;
  680.     miStepDash((int)pGC->dashOffset, &dinfo.dashIndexInit,
  681.            (unsigned char *) pGC->dash, (int)pGC->numInDashList,
  682.            &dinfo.dashOffsetInit);
  683.     }
  684.     points = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * numPts);
  685.     if (!points)
  686.     {
  687.     if (dospans)
  688.     {
  689.         DEALLOCATE_LOCAL(widths);
  690.     }
  691.     return;
  692.     }
  693.     for (arc = parcs, i = narcs; --i >= 0; arc++)
  694.     {
  695.     if (miCanZeroArc(arc))
  696.     {
  697.         if (pGC->lineStyle == LineSolid)
  698.         pts = miZeroArcPts(arc, points);
  699.         else
  700.         {
  701.         pts = points;
  702.         oddPts = &points[(numPts >> 1) - 1];
  703.         miZeroArcDashPts(pGC, arc, &dinfo,
  704.                  oddPts + 1, maxPts, &pts, &oddPts);
  705.         }
  706.         n = pts - points;
  707.         if (!dospans)
  708.         (*pGC->ops->PolyPoint)(pDraw, pGC, CoordModeOrigin, n, points);
  709.         else
  710.         {
  711.         if (n > maxw)
  712.         {
  713.             while (maxw < n)
  714.             widths[maxw++] = 1;
  715.         }
  716.         if (pGC->miTranslate)
  717.         {
  718.             for (pt = points; pt != pts; pt++)
  719.             {
  720.             pt->x += pDraw->x;
  721.             pt->y += pDraw->y;
  722.             }
  723.         }
  724.         (*pGC->ops->FillSpans)(pDraw, pGC, n, points, widths, FALSE);
  725.         }
  726.         if (pGC->lineStyle != LineDoubleDash)
  727.         continue;
  728.         if ((pGC->fillStyle == FillSolid) ||
  729.         (pGC->fillStyle == FillStippled))
  730.         {
  731.         DoChangeGC(pGC, GCForeground, (XID *)&pGC->bgPixel, 0);
  732.         ValidateGC(pDraw, pGC);
  733.         }
  734.         pts = &points[numPts >> 1];
  735.         oddPts++;
  736.         n = pts - oddPts;
  737.         if (!dospans)
  738.         (*pGC->ops->PolyPoint)(pDraw, pGC, CoordModeOrigin, n, oddPts);
  739.         else
  740.         {
  741.         if (n > maxw)
  742.         {
  743.             while (maxw < n)
  744.             widths[maxw++] = 1;
  745.         }
  746.         if (pGC->miTranslate)
  747.         {
  748.             for (pt = oddPts; pt != pts; pt++)
  749.             {
  750.             pt->x += pDraw->x;
  751.             pt->y += pDraw->y;
  752.             }
  753.         }
  754.         (*pGC->ops->FillSpans)(pDraw, pGC, n, oddPts, widths, FALSE);
  755.         }
  756.         if ((pGC->fillStyle == FillSolid) ||
  757.         (pGC->fillStyle == FillStippled))
  758.         {
  759.         DoChangeGC(pGC, GCForeground, (XID *)&fgPixel, 0);
  760.         ValidateGC(pDraw, pGC);
  761.         }
  762.     }
  763.     }
  764.     if (dospans)
  765.     {
  766.     DEALLOCATE_LOCAL(widths);
  767.     }
  768.     DEALLOCATE_LOCAL(points);
  769. }
  770.